Skip to content

🛡️ Sentinel: [CRITICAL] Fix TOCTOU and DoS via file stat checks - #81

Open
ivangegovdve-sudo wants to merge 1 commit into
mainfrom
sentinel-fix-toctou-dos-5613353413879271950
Open

🛡️ Sentinel: [CRITICAL] Fix TOCTOU and DoS via file stat checks#81
ivangegovdve-sudo wants to merge 1 commit into
mainfrom
sentinel-fix-toctou-dos-5613353413879271950

Conversation

@ivangegovdve-sudo

Copy link
Copy Markdown
Owner

🚨 Severity: CRITICAL
💡 Vulnerability: Used path.stat().st_size to check file size before reading the entire file, which exposes a Time-of-Check to Time-of-Use (TOCTOU) vulnerability. Additionally, using .exists() instead of .is_file() allows device files (like /dev/zero) to report a size of 0 and bypass the check, leading to an unbounded memory consumption DoS attack when read_text() is called.
🎯 Impact: Could allow an attacker or misconfiguration to crash the application via out-of-memory errors (DoS) by pointing to a special device file or exploiting the race condition.
🔧 Fix: Replaced .exists() with .is_file() and used a secure bounded read f.read(limit + 1) and explicit open() context manager to enforce the size limit directly at read time, entirely eliminating both the TOCTOU race condition and the /dev/zero device file bypass.
✅ Verification: Ran uv run pytest and verified all tests pass, confirmed bounded reads correctly raise ValueError for large files via inspection, and recorded learnings in .jules/sentinel.md.


PR created automatically by Jules for task 5613353413879271950 started by @ivangegovdve-sudo

Co-authored-by: ivangegovdve-sudo <225339531+ivangegovdve-sudo@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates several file-backed adapters to mitigate TOCTOU vulnerabilities and DoS risks by replacing file size stat checks with bounded reads and ensuring paths are regular files. Feedback suggests enhancing robustness in the checkpoint store by handling potential file and JSON parsing errors. Additionally, it is recommended to replace the recurring magic number for the file size limit with a shared constant to improve maintainability across the adapters.

Comment on lines +237 to 243
with open(path, encoding="utf-8") as f:
content = f.read(10 * 1024 * 1024 + 1)
if len(content) > 10 * 1024 * 1024:
raise ValueError(f"Checkpoint file {path} exceeds 10MB size limit")

parsed = json.loads(content)
return parsed if isinstance(parsed, dict) else {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This implementation can be improved in two ways:

  1. Robustness: The code doesn't handle potential OSError from file operations or json.JSONDecodeError from parsing. This could lead to unhandled exceptions, whereas other adapters in the codebase handle these gracefully. For consistency and robustness, this one should too.
  2. Maintainability: The file size limit 10 * 1024 * 1024 is a magic number. Defining it as a constant improves readability and makes it easier to change, especially since it's used across multiple files.

Here's a suggestion that addresses both points. Ideally, the MAX_FILE_SIZE_BYTES constant would be defined at the module level to be shared across all adapters.

    MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024  # 10MB
    try:
        with open(path, encoding="utf-8") as f:
            content = f.read(MAX_FILE_SIZE_BYTES + 1)
            if len(content) > MAX_FILE_SIZE_BYTES:
                raise ValueError(f"Checkpoint file {path} exceeds 10MB size limit")

        if not content.strip():
            return {}

        parsed = json.loads(content)
        return parsed if isinstance(parsed, dict) else {}
    except (OSError, json.JSONDecodeError, ValueError):
        return {}

Comment on lines +111 to +112
content = f.read(10 * 1024 * 1024 + 1)
if len(content) > 10 * 1024 * 1024:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The file size limit 10 * 1024 * 1024 is a magic number. To improve readability and maintainability, consider defining it as a shared constant (e.g., _MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024) at the module level or in a common constants file and using it here and in the other adapters.

Comment on lines +48 to +49
content = f.read(10 * 1024 * 1024 + 1)
if len(content) > 10 * 1024 * 1024:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The file size limit 10 * 1024 * 1024 is a magic number. To improve readability and maintainability, consider defining it as a shared constant (e.g., _MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024) at the module level or in a common constants file and using it here and in the other adapters.

Comment on lines +42 to +43
content = f.read(10 * 1024 * 1024 + 1)
if len(content) > 10 * 1024 * 1024:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The file size limit 10 * 1024 * 1024 is a magic number. To improve readability and maintainability, consider defining it as a shared constant (e.g., _MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024) at the module level or in a common constants file and using it here and in the other adapters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant